package com.aaa.tars.util;

import com.aaa.tars.entity.OperateLog;
import com.aaa.tars.entity.User;
import com.aaa.tars.service.OperateLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * @FileName: RecordLogUtil
 * @Description: 操作日志记录工具类
 * @Author: xm
 * @CreateTime: 2025/9/18 10:36
 * @Version: 1.0.0
 */
@Component
@Aspect //标识当前类时为切面实现类
public class RecordOperateLogUtil {


    @Resource
    private OperateLogService operateLogService;

    @Resource
    private HttpSession session;

    @Resource
    private HttpServletRequest request;
    /**
     * 编写一个切入点方法  方法可以不写任何代码   让日志记录方法和业务方法产生联系的一个方法
     */
    //* 通配符
    //第1个*  表示方法的任意权限修饰符和返回值
    //第2个*  表示包com.aaa.sbm.service.impl下的所有类
    //第3个*  表示以delete开头的所有方法
    //  com.aaa.sbm.service.impl.DeptServiceImpl.add 找到了要加入日志方法
    // ..  0到多个参数

    //execution(* com.aaa.sbm.service.impl.*.add(..))  拦截com.aaa.sbm.service.impl下的所有类的add方法
    @Pointcut(value = "execution(* com.aaa.tars.service.impl.*.add(..))" +
            "&&!execution(* com.aaa.tars.service.impl.OperateLogServiceImpl.add(..))"+
            "||execution(* com.aaa.tars.service.impl.*.insert(..))"+
            "||execution(* com.aaa.tars.service.impl.*.update(..))"+
            "||execution(* com.aaa.tars.service.impl.*.delete*(..))"

    )
//    @Pointcut(value = "(execution(* com.aaa.sbm.service.impl.*.add(..))" +
//            "||execution(* com.aaa.sbm.service.impl.*.insert(..))"+
//            "||execution(* com.aaa.sbm.service.impl.*.update(..))"+
//            "||execution(* com.aaa.sbm.service.impl.*.delete*(..)))"+
//            "&&!execution(* com.aaa.sbm.service.OperateLogServiceImpl.add(..))"
//    )
    //拦截所有方法，排除query开头的
//    @Pointcut(value = "execution(* com.aaa.sbm.service.impl.*.*(..))" +
//            "&&!execution(* com.aaa.sbm.service.impl.*.query*(..))"
//    )
    //配置切入点
    //execution() 放入真正的切入点表达式
    public void cutPoint(){
    }

    /**
     * 后置通知（在执行业务方法之后执行的方法）  记录日志功能
     * @param joinPoint
     */
    @AfterReturning(pointcut = "cutPoint()") //表示当前记录日志功能是在真正业务方法执行之后执行After
    public  void   recordOperateLog(JoinPoint joinPoint){
        recordLog(joinPoint,0,null);
//        //JoinPoint连接点  spring提供一个类，可以获取连接点信息
//        //获取正在执行的方法的名称
//        String executeMethodName = joinPoint.getSignature().getName();
//        System.out.println("正在执行的方法的名称为："+executeMethodName);
//
//        //System.out.println("模拟-------记录日志功能----111--222---");
//        //实例化添加对象
//        OperLog operLog = new OperLog();
//        //设置属性
//
//        //获取到目标对象 根据目标对象一个一个判断属于哪个模块
//        operLog.setTitle("系统管理模块");
//        //定义业务类型
//        int businessType = 1;
//        //executeMethodName = add/insert/update/deleteById
//        //if(executeMethodName.contains("update")||executeMethodName.contains("modify")){
//        if(executeMethodName.contains("update")){
//            businessType = 2;
//        }else if(executeMethodName.contains("delete")){
//            businessType = 3;
//        }
//        //业务类型（1新增 2修改 3删除）
//        operLog.setBusinessType(businessType);
//        //获取目标对象 targetName=com.aaa.sbm.service.impl.DeptServiceImpl 或者com.aaa.sbm.service.impl.UserServiceImpl
//        String targetName = joinPoint.getTarget().getClass().getName();
//        //方法名称（哪个类中的哪个方法）  com.aaa.sbm.service.impl.DeptServiceImpl.add  com.aaa.sbm.service.impl.DeptServiceImpl.update...
//        operLog.setMethod(targetName+"."+executeMethodName);
//        //操作类别（0其它 1后台用户 2手机端用户）
//        operLog.setOperatorType(1);
//        //获取当前登录的用户信息
//        User user =  (User)session.getAttribute("userInfo");
//        //判断
//        if(user!=null){
//            //操作人员 (userName)
//            operLog.setOperName(user.getUserName());
//            //部门信息
//            operLog.setDeptName(user.getDeptId()+"");
//        }
//        //使用HttpServletRequest对象获取当前请求URL
//        String requestURL = request.getRequestURL().toString();
//        //请求URL  http://localhost:19090/dept/add  http://localhost:19090/dept/update  http://localhost:19090/dept/deleteById
//        operLog.setOperUrl(requestURL);
//        //请求IP地址
//        String remoteAddr = request.getRemoteAddr();
//        System.out.println("请求的IP为："+remoteAddr);
//        operLog.setOperIp(remoteAddr);
//        //操作地点
//         operLog.setOperLocation("郑州");
//         //使用JoinPoint对象获取所有参数
//        Object[] argArray = joinPoint.getArgs();
//         //判断数组
//        if(argArray!=null&&argArray.length>0){
//            String firstArgName = argArray[0].getClass().getName();
//            //请求参数 com.aaa.sbm.entity.Dept
//            operLog.setOperParam(firstArgName);
//        }
//        //状态 操作状态（0正常 1异常）
//        operLog.setStatus(0);
//        //设置日志操作时间 获取当前时间
//        operLog.setOperTime(new Date());
//
//        operateService.add(operLog);
    }

    /**
     * 异常通知（在执行业务方法中出现了异常要执行的方法）   记录异常日志
     * @param joinPoint
     */
    @AfterThrowing(pointcut = "cutPoint()",throwing = "e2") //表示当前记录日志功能是在真正业务方法执行之后执行After
    public  void   recordErrorOperateLog(JoinPoint joinPoint,Exception e2){
        recordLog(joinPoint,1,e2);
    }

    /**
     * 封装一个方法（没测试）
     * @param joinPoint
     * @param status
     * @param e2
     */
    private void recordLog(JoinPoint joinPoint,Integer status,Exception e2){
        //JoinPoint连接点  spring提供一个类，可以获取连接点信息
        //获取正在执行的方法的名称
        String executeMethodName = joinPoint.getSignature().getName();
        System.out.println("正在执行的方法的名称为："+executeMethodName);

        //System.out.println("模拟-------记录日志功能----111--222---");
        //实例化添加对象
        OperateLog operLog = new OperateLog();
        //设置属性

        //获取到目标对象 根据目标对象一个一个判断属于哪个模块
        operLog.setTitle("系统管理模块");
        //定义业务类型
        int businessType = 1;
        //executeMethodName = add/insert/update/deleteById
        //if(executeMethodName.contains("update")||executeMethodName.contains("modify")){
        if(executeMethodName.contains("update")){
            businessType = 2;
        }else if(executeMethodName.contains("delete")){
            businessType = 3;
        }
        //业务类型（1新增 2修改 3删除）
        operLog.setBusinessType(businessType);
        //获取目标对象 targetName=com.aaa.sbm.service.impl.DeptServiceImpl 或者com.aaa.sbm.service.impl.UserServiceImpl
        String targetName = joinPoint.getTarget().getClass().getName();
        //方法名称（哪个类中的哪个方法）  com.aaa.sbm.service.impl.DeptServiceImpl.add  com.aaa.sbm.service.impl.DeptServiceImpl.update...
        String method = targetName+"."+executeMethodName;
        // 处理特殊字符，避免SQL执行错误
        if (method != null && method.length() > 200) {
            method = method.substring(0, 200);
        }
        operLog.setMethod(method);
        //操作类别（0其它 1后台用户 2手机端用户）
        operLog.setOperatorType(1);
        //获取当前登录的用户信息
        User user =  (User)session.getAttribute("userInfo");
        //判断
        if(user!=null){
            //操作人员 (userName)
            operLog.setOperName(user.getUserName());
            //部门信息
            operLog.setDeptName(user.getDeptId()+"");
        }
        //使用HttpServletRequest对象获取当前请求URL
        String requestURL = request.getRequestURL().toString();
        //请求URL  http://localhost:19090/dept/add  http://localhost:19090/dept/update  http://localhost:19090/dept/deleteById
        operLog.setOperUrl(requestURL);
        //请求IP地址
        String remoteAddr = request.getRemoteAddr();
        System.out.println("请求的IP为："+remoteAddr);
        operLog.setOperIp(remoteAddr);
        //操作地点
        operLog.setOperLocation("郑州");
        //使用JoinPoint对象获取所有参数
        Object[] argArray = joinPoint.getArgs();
        //判断数组
        if(argArray!=null&&argArray.length>0){
            String firstArgName = argArray[0].getClass().getName();
            // 处理特殊字符，避免SQL执行错误
            if (firstArgName != null && firstArgName.length() > 200) {
                firstArgName = firstArgName.substring(0, 200);
            }
            //请求参数 com.aaa.sbm.entity.Dept
            operLog.setOperParam(firstArgName);
        }
        //状态 操作状态（0正常 1异常）
        operLog.setStatus(status);
        //异常信息
        if(e2!=null){
            String errorMsg = e2.getClass().getName();
            // 处理特殊字符，避免SQL执行错误
            if (errorMsg != null && errorMsg.length() > 200) {
                errorMsg = errorMsg.substring(0, 200);
            }
            operLog.setErrorMsg(errorMsg);
        }

        //设置日志操作时间 获取当前时间
        operLog.setOperTime(new Date());

        operateLogService.add(operLog);
    }
}
